chore: pin mcp>=1.28.1,<2 ahead of MCP Python SDK v2 stable release - #5840
Conversation
The MCP Python SDK v2 stable release (targeted 2026-07-27/28) is a major rework with pervasive breaking changes (FastMCP rename, mcp.types split, WebSocket transport removal). Upstream guidance is to add a <2 upper bound before the release. Bound every first-party manifest and regenerate uv.lock; resolution stays on the 1.28.x line. fastmcp needs no change: its own mcp dependency is intersected with our direct <2 pin. Closes IBM#5839 Signed-off-by: Ahmad Al Tamimi <altamimi.dev@gmail.com>
msureshkumar88
left a comment
There was a problem hiding this comment.
E2E verification — real environment run
Checked out this PR's exact head commit locally (5839-pin-mcp-below-2 @ a6e7f1545) and ran the fix through the actual toolchain rather than just re-reading the diff.
Config: uv 0.10.2, Python 3.12.3, local checkout, --extra plugins resolve, live PyPI query (network confirmed reachable).
Commands + results:
grep -rEn '"mcp(>=|==|~=|>)[0-9]...' --include='*.toml' --include='*.txt' .— swept every first-party manifest. All 8 lines bounded,<2(7 atmcp>=1.28.1,<2, cookiecutter template atmcp>=1.0.0,<2). Zero unboundedmcppins left in the tree.uv lock --check— pass,uv.lockmatches the manifests as committed, no drift.uv sync --extra plugins— real dependency resolve/install against this PR's lock. Succeeded (376 packages resolved).- Runtime assertion (
importlib.metadata.version("mcp")) — resolved to1.28.1,< 2holds. (Note:mcp.__version__doesn't exist as a module attribute — usedimportlib.metadatainstead.) - Live PyPI check (
pypi.org/pypi/mcp/json) — latest publishedmcpright now is still1.28.1; v2 stable hasn't landed yet as of this review, confirming the pin is precautionary/pre-emptive rather than already-broken — exactly the intended defensive posture ahead of the announced release window. import fastmcpagainst the newly-bounded resolution — imports cleanly, confirming the PR's claim thatfastmcp's own unboundedmcpdependency is safely intersected by the direct<2pin without needing its own bound.
All 6 steps passed. Combined with this PR's already-green CI on the same commit (full make test, 20847 passed, container builds for all 4 architectures, dependency-review, DCO) this covers both the resolution behavior specific to this fix and the broader regression surface.
Review outcome: Approve
No blocking or functionally-impacting findings — the fix is minimal, matches every acceptance criterion in #5839, and verified to actually bound resolution as intended.
Two small optional, non-blocking follow-ups (not required for merge):
pyproject.toml:124— the other non-obvious pins in this file carry an inline comment (e.g.# Transitive pin (alembic)); a short one here (# <2: ahead of v2 stable, breaking changes — see #5839) would help future maintainers know when it's safe to lift.- Worth opening a tracking issue for the eventual v2 migration / pin removal, referenced from here, so the bound doesn't quietly outlive its purpose once mcp 1.x stops getting patches.
Pull Request
🔗 Related Issue
Closes #5839
📝 Summary
Adds a protective
<2upper bound to themcpdependency across all first-party manifests ahead of the MCP Python SDK v2 stable release (targeted 2026-07-27/28), which is a major rework with pervasive breaking changes (FastMCP→MCPServer rename,mcp.typessplit-out, WebSocket transport removal). Every shipped manifest is bounded tomcp>=1.28.1,<2anduv.lockis regenerated; resolution is unchanged and stays on the 1.28.x line.fastmcpneeds no change — its ownmcpdependency is intersected with our direct<2pin, so our bound constrains the whole resolution.The cookiecutter template (
mcp-servers/templates/python/...) was also bounded (mcp>=1.0.0,<2) for consistency, keeping its lower floor. The v2 migration itself is explicitly out of scope per the issue — this is a purely protective packaging change.📏 Reviewability
triage🏷️ Type of Change
🧪 Verification
grep -rEn 'mcp(>=|==|~=|>)[0-9]' --include='*.toml' --include='*.txt' ...,<2uv lockgrep -c 'specifier = ">=1.28.1,<2"' uv.lockgrep -A1 '^name = "mcp"$' uv.lock | grep versionversion = "1.28.1"uv sync --extra plugins && uv run python -c "import mcp, mcp.types; ..."mcp 1.28.1 OKmake testOnly the resolved-graph metadata changed (mcp specifier); resolved package versions are identical, so the change is runtime-neutral today. Container build is covered by CI — the resolved graph is unchanged so the build cannot differ.
✅ Checklist
make black isort pre-commit)📓 Notes
uv.lockalso shows deterministic byproduct churn from the repo's ownexclude-newer-span = "P10D"config re-resolving on lock (an absoluteexclude-newertimestamp and a couple of transitive marker refinements). No resolved package version changed.